package main

import (
	"bufio"
	"bytes"
	"fmt"
	"github.com/sirupsen/logrus"
	"os"
	"path"
)

// 颜色 对应的序号
const (
	red    = 31
	yellow = 33
	blue   = 36
	gray   = 37
)

type LogFormatter struct {
	Prefix string //前缀 相等于给这个日志增加了一个标识 [gorm][2023-05-27 16:36:54] [warning] main.go:75 main.main 你好 [gorm]就是日志前缀
}

// Format 实现Formatter(entry *logrus.Entry) ([]byte, error)接口
func (t *LogFormatter) Format(entry *logrus.Entry) ([]byte, error) {
	//根据不同的level去展示颜色
	var levelColor int
	switch entry.Level {
	case logrus.DebugLevel, logrus.TraceLevel:
		levelColor = gray
	case logrus.WarnLevel:
		levelColor = yellow
	case logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel:
		levelColor = red
	default:
		levelColor = blue
	}
	//设置文本buffer 缓冲区
	var b *bytes.Buffer
	if entry.Buffer != nil {
		b = entry.Buffer
	} else {
		b = &bytes.Buffer{}
	}
	//自定义日期格式
	timestamp := entry.Time.Format("2006-01-02 15:04:05")
	if entry.HasCaller() {
		//自定义文件行号和文件名  path.Base(entry.Caller.File) 只取相对路径main.go,不取绝对路径D:\go\src\code.oldboyedu.com\studygo\day05\logrus_log3\main.go
		funcVal := entry.Caller.Function
		fileVal := fmt.Sprintf("%s:%d", path.Base(entry.Caller.File), entry.Caller.Line)
		//自定义输出格式  把内容输出到writer里面
		fmt.Fprintf(b, "[%s][%s] \x1b[%dm[%s]\x1b[0m %s %s %s %s\n", t.Prefix, timestamp, levelColor, entry.Level, fileVal, funcVal, getExtraFields(entry), entry.Message)
	} else {
		fmt.Fprintf(b, "[%s][%s] \x1b[%dm[%s]\x1b[0m %s %s\n", t.Prefix, timestamp, levelColor, entry.Level, getExtraFields(entry), entry.Message)
	}
	return b.Bytes(), nil
}

var mlog *logrus.Logger
var flog *logrus.Logger

func init() {
	file, err := os.OpenFile("./test.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		mlog.Error("打开%s文件失败", "test.log")
		flog.Error("打开%s文件失败", "test.log")
		return
	}
	mlog = NewconsoleLog()
	flog = NewInputfileLog(file)
}

//设置控制台输出格式
func NewconsoleLog() *logrus.Logger {
	mLog := logrus.New()                             //新建一个实例
	mLog.SetOutput(os.Stdout)                        //设置输出类型
	mLog.SetReportCaller(true)                       //开启返回函数名和行号
	mLog.SetFormatter(&LogFormatter{Prefix: "test"}) //设置自己定义的Formatter
	mLog.SetLevel(logrus.DebugLevel)                 //设置最低的Level
	return mLog
}

//设置文件中的输出格式
func NewInputfileLog(file *os.File) *logrus.Logger {
	fLog := logrus.New()                             //新建一个实例
	fLog.SetOutput(file)                             //设置输出类型
	fLog.SetReportCaller(true)                       //开启返回函数名和行号
	fLog.SetFormatter(&LogFormatter{Prefix: "test"}) //设置自己定义的Formatter
	fLog.SetLevel(logrus.DebugLevel)                 //设置最低的Level
	return fLog
}

// 获取额外的字段   将新增加的日志字段增加到打印的日志文件中
func getExtraFields(entry *logrus.Entry) string {
	result := ""
	for k, v := range entry.Data {
		result += fmt.Sprintf("%s=%v,", k, v)
	}
	if result != "" {
		result = "[" + result + "] "
	}
	return result
}
func getwritefile() {
	content := "北京欢迎你"
	//defer file.Close()
	writer := bufio.NewWriter(flog.Out)
	//将数据先写到缓存中
	for i := 0; i < 4; i++ {
		_, err := writer.WriteString(content + "\n")
		mlogwrite := mlog.WithFields(logrus.Fields{
			"appid":   i,
			"content": content,
		})
		flogwrite := flog.WithFields(logrus.Fields{
			"appid":   i,
			"content": content,
		})
		if err == nil {
			flogwrite.Info("写数据成功")
			mlogwrite.Info("写数据成功")
		} else {
			flogwrite.Error("写数据失败")
			mlogwrite.Error("写数据失败")
			break
		}
	}
	err := writer.Flush()
	if err != nil {
		flog.Error("将数据从内存持久化到文件失败")
		mlog.Error("将数据从内存持久化到文件失败")
		return
	} //将缓存中的内容写入文件中

}
func main() {
	getwritefile()
}
